﻿using System;
using System.Windows.Forms;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace DiveDeeper.VsxLibrary.Core
{
  // ==================================================================================
  /// <summary>
  /// This static class is a wrapper class around the SvSUIShell operations.
  /// </summary>
  // ==================================================================================
  public static class VsUIShell
  {
    #region MessageBox methods

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="text">Message text</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text)
    {
      return ShowMessageBoxInternal(null, text, string.Empty, 0, MessageBoxButtons.OK,
        MessageBoxDefaultButton.Button1, MessageBoxIcon.Information, false);
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="text">Message text</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text, string title)
    {
      return ShowMessageBoxInternal(title, text, string.Empty, 0, MessageBoxButtons.OK,
        MessageBoxDefaultButton.Button1, MessageBoxIcon.Information, false);
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="text">Message text</param>
    /// <param name="buttons">Buttons to show on the message box</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text, string title,
      MessageBoxButtons buttons)
    {
      return ShowMessageBoxInternal(title, text, string.Empty, 0, buttons,
        MessageBoxDefaultButton.Button1, MessageBoxIcon.Information, false);
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="text">Message text</param>
    /// <param name="buttons">Buttons to show on the message box</param>
    /// <param name="icon">Icon to display in the message box.</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text, string title,
      MessageBoxButtons buttons, MessageBoxIcon icon)
    {
      return ShowMessageBoxInternal(title, text, string.Empty, 0, buttons,
        MessageBoxDefaultButton.Button1, icon, false);
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="text">Message text</param>
    /// <param name="buttons">Buttons to show on the message box</param>
    /// <param name="defaultButton">Default message box button.</param>
    /// <param name="icon">Icon to display in the message box.</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text, string title,
      MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
    {
      return ShowMessageBoxInternal(title, text, string.Empty, 0, buttons,
        defaultButton, icon, false);
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="text">Message text</param>
    /// <param name="helpFilePath">Help file name</param>
    /// <param name="buttons">Buttons to show on the message box</param>
    /// <param name="defaultButton">Default message box button.</param>
    /// <param name="icon">Icon to display in the message box.</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text, string title,
      MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton,
      string helpFilePath)
    {
      return ShowMessageBoxInternal(title, text, helpFilePath, 0, buttons,
        defaultButton, icon, false);
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="text">Message text</param>
    /// <param name="helpFilePath">Help file name</param>
    /// <param name="helpTopic">Help topic identifier</param>
    /// <param name="buttons">Buttons to show on the message box</param>
    /// <param name="defaultButton">Default message box button.</param>
    /// <param name="icon">Icon to display in the message box.</param>
    /// <returns>
    /// Result of the MessageBox.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static DialogResult ShowMessageBox(string text, string title,
      MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton,
      string helpFilePath, uint helpTopic)
    {
      return ShowMessageBoxInternal(title, text, helpFilePath, helpTopic, buttons,
        defaultButton, icon, false);
    }

    #endregion

    #region SaveDocDataToFile

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Helper method used by editors that implement the IVsPersistDocData interface.
    /// </summary>
    /// <param name="grfSave">Specifies file Save options.</param>
    /// <param name="pPersistFile">
    /// Pointer to the IUnknown interface of the file in which the doc data is to 
    /// be saved.
    /// </param>
    /// <param name="pszUntitledPath">
    /// File path to which the doc data for an as-yet unsaved document is to be saved.
    /// </param>
    /// <param name="pbstrDocumentNew">New document file name.</param>
    /// <param name="pfCanceled">
    /// Set to true if the user aborts the save by clicking the Cancel button.
    /// </param>
    /// <returns>
    /// If the method succeeds, it returns S_OK. If it fails, it returns an error code.
    /// </returns>
    // --------------------------------------------------------------------------------
    public static int SaveDocDataToFile(VSSAVEFLAGS grfSave, object pPersistFile,
      string pszUntitledPath, out string pbstrDocumentNew, out int pfCanceled)
    {
      return UIShell.SaveDocDataToFile(grfSave, pPersistFile, pszUntitledPath,
                                       out pbstrDocumentNew, out pfCanceled);
    }

    #endregion

    #region SetWaitCursor

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Changes the cursor to the hourglass cursor.
    /// </summary>
    // --------------------------------------------------------------------------------
    public static void SetWaitCursor()
    {
      UIShell.SetWaitCursor();
    }

    #endregion

    #region Additional methods

    // --------------------------------------------------------------------------------
    /// <summary>
    /// This method shows up the property window.
    /// </summary>
    // --------------------------------------------------------------------------------
    public static void ShowPropertiesWindow()
    {
      Guid propertyBrowser = new Guid(ToolWindowGuids.PropertyBrowser);
      IVsWindowFrame propFrame;
      UIShell.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fForceCreate,
                             ref propertyBrowser, out propFrame);
      if (propFrame != null) propFrame.Show();
    }

    #endregion

    #region Private methods

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Gets the IVsUIShell service instance.
    /// </summary>
    // --------------------------------------------------------------------------------
    private static IVsUIShell UIShell
    {
      get
      {
        return Package.GetGlobalService(typeof(SVsUIShell)) as IVsUIShell;
      }
    }

    // --------------------------------------------------------------------------------
    /// <summary>
    /// Displays a Visual Studio message box.
    /// </summary>
    /// <param name="title">Title of the message</param>
    /// <param name="message">Message text</param>
    /// <param name="helpFile">Help file name</param>
    /// <param name="helpTopic">Help topic identifier</param>
    /// <param name="buttons">Buttons to show on the message box</param>
    /// <param name="defButton">Default message box button.</param>
    /// <param name="icon">Icon to display in the message box.</param>
    /// <param name="sysAlert">MB_SYSTEMMODAL flag</param>
    /// <returns>
    /// MessageBox result converted to DialogResult.
    /// </returns>
    // --------------------------------------------------------------------------------
    private static DialogResult ShowMessageBoxInternal(string title, string message, string helpFile,
      uint helpTopic, MessageBoxButtons buttons, MessageBoxDefaultButton defButton,
      MessageBoxIcon icon, bool sysAlert)
    {
      Guid clsid = Guid.Empty;
      int result;
      ErrorHandler.ThrowOnFailure(UIShell.ShowMessageBox(
                 0,
                 ref clsid,
                 title,
                 message,
                 helpFile,
                 helpTopic,
                 VsxConverter.ConvertToOleMsgButton(buttons),
                 VsxConverter.ConvertToOleMsgDefButton(defButton),
                 VsxConverter.ConvertToOleMsgIcon(icon),
                 sysAlert ? 1 : 0,
                 out result));
      return VsxConverter.Win32ResultToDialogResult(result);
    }

    #endregion
  }
}
